package com.stu.mapper;

import com.stu.pojo.User;
import org.apache.ibatis.annotations.*;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 使用 MyBatis 注解方式实现数据库操作
 * @author zy
 * @date 2025/4/12
 */
@Mapper // 标识为 MyBatis 的 Mapper 接口
public interface UserMapper {

    /**
     * 插入新用户记录
     * @param user 用户实体对象（不需要设置 userId，数据库自增生成）
     * @return 受影响的行数
     * @apiNote 会自动将生成的主键回填到 user.userId 属性
     */
    @Insert("INSERT INTO user (user_name, user_password, user_tel, user_email, " +
            "user_created, user_updated, status, version) " +
            "VALUES (#{userName}, #{userPassword}, #{userTel}, #{userEmail}, " +
            "#{userCreated}, #{userUpdated}, #{status}, #{version})")
    @Options(useGeneratedKeys = true, keyProperty = "userId") // 关键配置：获取自增主键
    int insert(User user);

    /**
     * 更新用户信息（带乐观锁检查）
     * @param user 用户实体对象（必须包含 userId 和 version）
     * @return 受影响的行数（返回 0 表示记录已被其他人修改）
     * @warning 需要先查询出最新 version 再调用此方法
     */
    @Update("UPDATE user SET " +
            "user_name = #{userName}, " +
            "user_password = #{userPassword}, " +
            "user_tel = #{userTel}, " +
            "user_email = #{userEmail}, " +
            "user_updated = #{userUpdated}, " +
            "status = #{status}, " +
            "version = version + 1 " +  // 版本号自增
            "WHERE user_id = #{userId} AND version = #{version}") // 乐观锁条件
    int update(User user);

    /**
     * 根据用户ID删除记录
     * @param userId 用户ID
     * @return 受影响的行数
     */
    @Delete("DELETE FROM user WHERE user_id = #{userId}")
    int deleteById(@Param("userId") Integer userId);

    // ========== 查询方法 ========== //

    /**
     * 定义用户实体的字段映射关系（数据库列名 → Java属性名）
     * 可以被其他查询方法通过 @ResultMap("userResultMap") 引用
     */
    @Results(id = "userResultMap", value = {
            @Result(property = "userId", column = "user_id", id = true), // id=true 表示主键
            @Result(property = "userName", column = "user_name"),
            @Result(property = "userPassword", column = "user_password"),
            @Result(property = "userTel", column = "user_tel"),
            @Result(property = "userEmail", column = "user_email"),
            @Result(property = "userCreated", column = "user_created"),
            @Result(property = "userUpdated", column = "user_updated"),
            @Result(property = "status", column = "status"),
            @Result(property = "version", column = "version")
    })
    @Select("SELECT * FROM user WHERE user_id = #{userId}")
    User selectById(@Param("userId") Integer userId);

    /**
     * 根据用户名查询用户
     * @param userName 用户名
     * @return 用户实体对象（未找到返回 null）
     */
    @Select("SELECT * FROM user WHERE user_name = #{userName}")
    @ResultMap("userResultMap") // 复用上面定义的映射规则
    User selectByUserName(@Param("userName") String userName);

    /**
     * 根据邮箱查询用户
     * @param userEmail 用户邮箱
     * @return 用户实体对象（未找到返回 null）
     */
    @Select("SELECT * FROM user WHERE user_email = #{userEmail}")
    @ResultMap("userResultMap")
    User selectByEmail(@Param("userEmail") String userEmail);

    /**
     * 查询所有状态匹配的用户
     * @param status 状态码（0=禁用，1=正常，2=锁定等）
     * @return 用户列表（无结果返回空集合）
     */
    @Select("SELECT * FROM user WHERE status = #{status}")
    @ResultMap("userResultMap")
    List<User> selectByStatus(@Param("status") Integer status);

    /**
     * 查询所有用户（慎用！数据量大时应分页）
     * @return 用户列表（无结果返回空集合）
     */
    @Select("SELECT * FROM user")
    @ResultMap("userResultMap")
    List<User> selectAll();

    // ========== 特定业务方法 ========== //

    /**
     * 更新用户状态
     * @param userId 用户ID
     * @param status 新状态码
     * @param now 更新时间
     * @return 受影响的行数
     */
    @Update("UPDATE user SET status = #{status}, user_updated = #{now} WHERE user_id = #{userId}")
    int updateStatus(@Param("userId") Integer userId,
                     @Param("status") Integer status,
                     @Param("now") LocalDateTime now);

    /**
     * 根据手机号查询用户（示例：可添加自定义查询方法）
     * @param userTel 手机号
     * @return 用户实体对象（未找到返回 null）
     */
    @Select("SELECT * FROM user WHERE user_tel = #{userTel}")
    @ResultMap("userResultMap")
    User selectByPhone(@Param("userTel") String userTel);
}
